package test_autoencode;

import java.io.IOException;
import java.util.Scanner;

/**
 * A class that handles encoding the captured file from the emulator.
 * @author Raiscan
 */
public class Encoder {

    private final String movieFile, romName, mencoderPath, mplayerPath, x264Path,
                   vorbisPath, mkvmergePath;
    private final int endGame;

    /**
     * Constructer class.
     * @param movieFile
     * @param romName
     * @param endGame
     */
    public Encoder(String mencoderPath, String mplayerPath, String x264Path, 
                   String vorbisPath, String mkvmergePath, String movieFile, String romName,
                   int endGame) {
        this.mencoderPath = mencoderPath;
        this.mplayerPath = mplayerPath;
        this.x264Path = x264Path;
        this.vorbisPath = vorbisPath;
        this.mkvmergePath = mkvmergePath;
        this.endGame = endGame;
        this.movieFile = movieFile;
        this.romName = romName;
    }

    /**
     * Encodes the video in X264 in very high quality. Suitable for TASVideos.
     * @return true if no errors reported, false otherwise.
     */
    public boolean mixLogo() {
        try {
            Process p = Runtime.getRuntime().exec(
                    mencoderPath+" logo.avi logo.avi capture.avi " +
                    "-aspect 4:3 " +
                    "-oac copy " +
                    "-mc 0 " +
                    "-ovc lavc " +
                    "-lavcopts vcodec=ffv1:vstrict=-2 " +
                    //"-msglevel all=-1 "+
                    //"-sub subtitle.sub " +
                    //"-font Arial " +
                    //"-subfont-text-scale 4 " +
                    //"-subpos 20 " +
                    //"-sub-bg-alpha 15 " +
                    "-o mixed.avi");
            OutputSoaker inStream = new OutputSoaker ("stin",p.getInputStream());
            OutputSoaker errStream = new OutputSoaker ("sterr",p.getErrorStream());
            inStream.start();
            errStream.start();
            int exitcode = p.waitFor();
            System.out.println(exitcode);
            return exitcode == 0;
        }
        catch (IOException e)
        {
            System.err.println("Error Running mencoder. " +
                    "Please check config.properties contains the correct path " +
                    "to mencoder.");
        }
        catch (Exception e)
        {
            System.err.println("Fatal error during logo mix");
            e.printStackTrace();
        }
        return false;
    }
    public boolean encodeVideo() {
        try {
            Process p = Runtime.getRuntime().exec(
                    x264Path+" \"mixed.avi\" "
                    + "--deldup 0.1:0.1:100:1:0.1 "
                    + "--versioninfo "
                    + "--ssim "
                    + "--crf 22 "
                    + "--keyint 600 "
                    + "--ref 16 "
                    + "--mixed-refs "
                    + "--no-fast-pskip "
                    + "--bframes 16 "
                    + "--b-adapt 2 "
                    + "--mbtree "
                    + "--weightb "
                    + "--direct auto "
                    + "--subme 10 "
                    + "--trellis 2 "
                    + "--partitions all "
                    + "--me umh "
                    + "--merange 64 "
                    + "--rc-lookahead 250 "
                    + "--fullrange on "
                    + "--threads auto "
                    + "--8x8dct "
                    + "--no-dct-decimate "
                    + "--output encodedvideo.mp4");
            //Scanner sc = new Scanner(p.getInputStream());

            //while (sc.hasNext()) {
            //    System.out.println(sc.nextLine());
            //}
            OutputSoaker inStream = new OutputSoaker ("stin",p.getInputStream());
            OutputSoaker errStream = new OutputSoaker ("sterr",p.getErrorStream());
            inStream.start();
            errStream.start();
            int exitcode = p.waitFor();
            return exitcode == 0;

        } catch (IOException e)
        {
            System.err.println("Error Running x264. " +
                    "Please check config.properties contains the correct path " +
                    "to x264.");
        } catch (Exception e) {
            System.err.println("error during encode video");
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Encodes the audio with Vorbis in decent quality. Suitable for TASVideos.
     * @return true if no errors reported, false otherwise.
     */
    public boolean encodeAudio() {
        try {
            Process p = Runtime.getRuntime().exec(mplayerPath+" mixed.avi -ao pcm:file=audio.wav -vc dummy -aid 1 -vo null");
            OutputSoaker inStream = new OutputSoaker ("stin",p.getInputStream());
            OutputSoaker errStream = new OutputSoaker ("sterr",p.getErrorStream());
            inStream.start();
            errStream.start();
            p.waitFor();
        } catch (IOException e)
        {
            System.err.println("Error Running mplayer. " +
                    "Please check config.properties contains the correct path " +
                    "to mplayer.");
            return false;
        }
        catch (Exception e) {
            System.err.println("error during encode audio");
            e.printStackTrace();
            return false;
        }
        try {
            Process p = Runtime.getRuntime().exec(vorbisPath+" -q0 audio.wav " +
                    "-o encodedaudio.ogg");
            OutputSoaker inStream = new OutputSoaker ("stin",p.getInputStream());
            OutputSoaker errStream = new OutputSoaker ("sterr",p.getErrorStream());
            inStream.start();
            errStream.start();
            int exitcode = p.waitFor();
            return exitcode == 0;
        }
        catch (IOException e)
        {
            System.err.println("Error Running vorbis. " +
                    "Please check config.properties contains the correct path " +
                    "to vorbis.");
        }
        catch (Exception e) {
            System.err.println("error during encode audio");
            e.printStackTrace();
        }
        return false;
    }
    public boolean mux()
    {
        try {
            Process p = Runtime.getRuntime().exec(
                    mkvmergePath+" encodedvideo.mp4 encodedaudio.ogg " +
                    "-o finished.mkv");
            //Scanner sc = new Scanner(p.getInputStream());

            //while (sc.hasNext()) {
            //    System.out.println(sc.nextLine());
            //}
            OutputSoaker inStream = new OutputSoaker ("stin",p.getInputStream());
            OutputSoaker errStream = new OutputSoaker ("sterr",p.getErrorStream());
            inStream.start();
            errStream.start();
            int exitcode = p.waitFor();
            return exitcode == 0;

        } catch (IOException e)
        {
            System.err.println("Error Running direct264. " +
                    "Please check config.properties contains the correct path " +
                    "to direct264.");
        } catch (Exception e) {
            System.err.println("error during encode video");
            e.printStackTrace();
        }
        return false;
    }
}
